package mqtt

import (
	"errors"
	"fmt"
	"github.com/eclipse/paho.mqtt.golang"
)

//订阅设备
type Device interface {
	MqttKey() string                               //设备标识
	MqttTopic() string                             //订阅主题
	MqttTopicHandler(topic string, message []byte) //消息接收方法
}

//订阅设备主题
func (c *MqttClient) SubscribeDevice(device Device) error {
	if device == nil {
		return nil
	}
	if !c.IsConnected() {
		return errors.New("MQTT connect is nil")
	}

	topic := device.MqttTopic()
	if len(topic) == 0 {
		return errors.New("MQTT Subscribe Device topic is empty")
	}
	if device.MqttTopicHandler == nil {
		return errors.New("MQTT Subscribe Device topicHandler is nil")
	}
	if len(device.MqttKey()) == 0 {
		return errors.New("MQTT Subscribe Device key is empty")
	}

	if _, ok := c.SubscribeMap[topic]; ok {
		return errors.New("MQTT has subscribed")
	}

	if _, ok := c.DevicesMap[topic]; ok {
		devices := c.DevicesMap[topic]
		var hasDevice bool
		for _, deviceTemp := range devices {
			if deviceTemp.MqttKey() == device.MqttKey() {
				hasDevice = true
			}
		}
		if !hasDevice {
			c.DevicesMap[topic] = append(c.DevicesMap[topic], device)

			fmt.Println("MQTT Subscribe,", "topic:", topic, "device:", device.MqttKey())
		}
		return nil
	} else {
		c.DevicesMap[topic] = []Device{}
	}

	token := c.Conn.Subscribe(topic, QoS0, func(client mqtt.Client, message mqtt.Message) {
		devices := c.DevicesMap[topic]
		for _, deviceTemp := range devices {
			deviceTemp.MqttTopicHandler(message.Topic(), message.Payload())
		}
	})
	if token.Wait() && token.Error() != nil {
		return token.Error()
	}
	c.DevicesMap[topic] = append(c.DevicesMap[topic], device)

	fmt.Println("MQTT Subscribe,", "topic:", topic, "device:", device.MqttKey())
	return nil
}

//取消设备订阅
func (c *MqttClient) UnsubscribeDevice(device Device) {
	if device == nil {
		return
	}
	if !c.IsConnected() {
		return
	}

	topic := device.MqttTopic()
	if len(topic) == 0 {
		return
	}

	devices := c.DevicesMap[topic]
	devicesTemp := []Device{}
	for _, deviceTemp := range devices {
		if deviceTemp.MqttKey() != device.MqttKey() {
			devicesTemp = append(devicesTemp, deviceTemp)
		}
	}
	c.DevicesMap[topic] = devicesTemp
	if len(devicesTemp) == 0 {
		c.Conn.Unsubscribe(topic)
		delete(c.DevicesMap, topic)
	}

	fmt.Println("MQTT Unsubscribe,", "topic:", topic, "device:", device.MqttKey())
}
